const axios = require('axios');
const { getLLMConfig } = require('./llm-config');

class LLMService {
  constructor() {
    this.config = getLLMConfig();
    this.provider = this.config.currentProvider;
    this.client = axios.create({
      timeout: this.config.timeout,
      maxRetries: this.config.maxRetries
    });
  }

  // 设置提供商
  setProvider(provider) {
    if (this.config.providers[provider]) {
      this.provider = provider;
      return true;
    }
    return false;
  }

  // 获取API配置
  getApiConfig() {
    const providerConfig = this.config.providers[this.provider];
    
    switch (this.provider) {
      case 'openai':
        return {
          url: `${providerConfig.baseURL}/chat/completions`,
          headers: {
            'Authorization': `Bearer ${providerConfig.apiKey}`,
            'Content-Type': 'application/json'
          },
          data: {
            model: providerConfig.model,
            temperature: 0.1,
            max_tokens: 2000
          }
        };

      case 'deepseek':
        return {
          url: `${providerConfig.baseURL}/chat/completions`,
          headers: {
            'Authorization': `Bearer ${providerConfig.apiKey}`,
            'Content-Type': 'application/json'
          },
          data: {
            model: providerConfig.model,
            temperature: 0.1,
            max_tokens: 2000
          }
        };

      case 'azure':
        return {
          url: `${providerConfig.endpoint}/openai/deployments/${providerConfig.deploymentName}/chat/completions?api-version=${providerConfig.apiVersion}`,
          headers: {
            'api-key': providerConfig.apiKey,
            'Content-Type': 'application/json'
          },
          data: {
            temperature: 0.1,
            max_tokens: 2000
          }
        };

      case 'xinference':
        return {
          url: `${providerConfig.baseURL}/chat/completions`,
          headers: {
            'Content-Type': 'application/json'
          },
          data: {
            model: providerConfig.model,
            temperature: 0.7,
            max_tokens: 12000,
            stream: false
          }
        };

      default:
        throw new Error(`不支持的提供商: ${this.provider}`);
    }
  }

  // 调用大模型API
  async callLLM(messages, customConfig = {}) {
    try {
      // 对于xinference等本地模型，不需要API密钥
      if (this.provider !== 'xinference' && !this.config.providers[this.provider]?.apiKey) {
        throw new Error(`未配置 ${this.provider} API密钥`);
      }

      const apiConfig = this.getApiConfig();
      const requestData = {
        ...apiConfig.data,
        messages,
        ...customConfig
      };

      const response = await this.client.post(apiConfig.url, requestData, {
        headers: apiConfig.headers
      });

      return response.data.choices[0].message.content;
    } catch (error) {
      console.error('大模型API调用失败:', error.message);
      throw error;
    }
  }

  // 分析页面内容
  async analyzePage(pageInfo, command) {
    const { url, title, content, domInfo, pageContext } = pageInfo;

    // 构建详细的DOM信息描述
    let domDescription = '';
    if (domInfo) {
      domDescription = `
详细DOM结构信息：
- 页面URL: ${domInfo.url || url}
- 页面标题: ${domInfo.title || title}
- 可交互元素数量: ${domInfo.interactiveElements?.length || 0}
- 表单数量: ${domInfo.forms?.length || 0}
- 标题层级: ${domInfo.headings?.length || 0}

可交互元素列表：`;

      // 添加可交互元素的详细信息
      if (domInfo.interactiveElements && domInfo.interactiveElements.length > 0) {
        domInfo.interactiveElements.slice(0, 20).forEach((element, index) => {
          domDescription += `
${index + 1}. ${element.tagName}[${element.type}]
   - 选择器: ${element.selector}
   - 文本内容: "${element.text}"
   - ID: ${element.id}
   - 类名: ${element.className}
   - 位置: (${element.position?.x}, ${element.position?.y})
   - 可见性: ${element.isVisible ? '可见' : '隐藏'}
   - 可点击: ${element.isClickable ? '是' : '否'}`;

          if (element.placeholder) domDescription += `\n   - 占位符: "${element.placeholder}"`;
          if (element.name) domDescription += `\n   - name属性: ${element.name}`;
          if (element.href) domDescription += `\n   - 链接: ${element.href}`;
        });
      }

      // 添加表单信息
      if (domInfo.forms && domInfo.forms.length > 0) {
        domDescription += '\n\n表单信息：';
        domInfo.forms.forEach((form, index) => {
          domDescription += `
${index + 1}. 表单 [${form.method}] ${form.action}
   - ID: ${form.id}
   - 元素数量: ${form.elements?.length || 0}`;

          if (form.elements && form.elements.length > 0) {
            form.elements.slice(0, 5).forEach(el => {
              domDescription += `
     - ${el.type}: ${el.name} ${el.required ? '(必填)' : ''}`;
            });
          }
        });
      }

      // 添加页面标题层级
      if (domInfo.headings && domInfo.headings.length > 0) {
        domDescription += '\n\n页面标题结构：';
        domInfo.headings.slice(0, 10).forEach(heading => {
          domDescription += `\n- H${heading.level}: "${heading.text}"`;
        });
      }
    }

    // 构建包含DOM信息的提示词
    let enhancedPrompt = this.config.pageAnalysisPrompt
      .replace('{url}', url || '未知')
      .replace('{title}', title || '未知')
      .replace('{content}', (content || '').substring(0, 2000))
      .replace('{command}', command);

    // 添加详细的DOM信息
    if (domDescription) {
      enhancedPrompt += '\n\n' + domDescription;
    }

    // 添加页面上下文信息
    if (pageContext) {
      enhancedPrompt += `\n\n页面上下文：
- 用户代理: ${pageContext.userAgent || ''}
- 时间戳: ${pageContext.timestamp || ''}`;
    }

    enhancedPrompt += `\n\n请基于以上详细的DOM信息和用户指令"${command}"，提供精确的分析和操作建议。`;

    const messages = [
      {
        role: 'system',
        content: `你是一个专业的网页自动化助手，精通DOM分析和Playwright自动化操作。
你需要：
1. 精确理解用户的自然语言指令
2. 分析提供的DOM结构信息
3. 制定可执行的操作步骤
4. 使用准确的CSS选择器
5. 评估操作风险和可行性

请确保返回有效的JSON格式，避免任何语法错误。`
      },
      {
        role: 'user',
        content: enhancedPrompt
      }
    ];

    try {
      const analysis = await this.callLLM(messages);
      console.log('LLM原始响应:', analysis);
      return this.parseAnalysisResult(analysis);
    } catch (error) {
      console.warn('页面分析失败，使用备用策略:', error.message);
      return this.getFallbackAnalysis(pageInfo, command);
    }
  }

  // 解析分析结果
  parseAnalysisResult(analysis) {
    try {
      // 清理可能的markdown代码块
      let cleanedAnalysis = analysis.replace(/```json\s*/, '').replace(/```\s*$/, '');

      // 尝试直接解析JSON
      let parsed;
      try {
        parsed = JSON.parse(cleanedAnalysis);
      } catch (parseError) {
        // 尝试提取JSON部分
        const jsonMatch = cleanedAnalysis.match(/\{[\s\S]*\}/);
        if (jsonMatch) {
          parsed = JSON.parse(jsonMatch[0]);
        } else {
          throw new Error('无法找到有效的JSON结构');
        }
      }

      // 验证和标准化解析结果
      const standardized = {
        summary: parsed.summary || '已完成页面分析',
        pageFunction: parsed.pageFunction || '未知页面功能',
        commandType: parsed.commandType || 'analysis',
        isExecutable: parsed.isExecutable !== undefined ? parsed.isExecutable : false,
        interactiveElements: Array.isArray(parsed.interactiveElements) ? parsed.interactiveElements : [],
        recommendedSteps: Array.isArray(parsed.recommendedSteps) ? parsed.recommendedSteps : [],
        risks: Array.isArray(parsed.risks) ? parsed.risks : [],
        confidence: typeof parsed.confidence === 'number' ? parsed.confidence : 0.5,
        rawAnalysis: analysis
      };

      return standardized;
    } catch (error) {
      console.warn('解析分析结果失败:', error.message);

      // 尝试提取关键信息
      const fallbackResult = {
        summary: '分析完成，但JSON解析失败',
        pageFunction: '页面功能分析',
        commandType: 'analysis',
        isExecutable: false,
        interactiveElements: [],
        recommendedSteps: [],
        risks: ['JSON解析失败，可能需要手动操作'],
        confidence: 0.3,
        rawAnalysis: analysis,
        parseError: error.message
      };

      // 尝试从原始文本中提取一些有用信息
      if (analysis.includes('按钮') || analysis.includes('button')) {
        fallbackResult.interactiveElements.push({
          type: 'button',
          description: '检测到按钮元素',
          selector: 'button'
        });
      }

      if (analysis.includes('输入框') || analysis.includes('input')) {
        fallbackResult.interactiveElements.push({
          type: 'input',
          description: '检测到输入框元素',
          selector: 'input'
        });
      }

      return fallbackResult;
    }
  }

  // 备用分析策略
  getFallbackAnalysis(pageInfo, command) {
    const { url, title } = pageInfo;
    
    // 基于常见页面模式的备用分析
    const commonSelectors = {
      login: {
        usernameInput: 'input[name="username"], input[type="text"], #username',
        passwordInput: 'input[name="password"], input[type="password"], #password',
        loginButton: 'button[type="submit"], input[type="submit"], .login-btn'
      },
      form: {
        input: 'input[type="text"], input[type="email"], textarea',
        button: 'button, input[type="submit"], input[type="button"]',
        select: 'select'
      }
    };

    return {
      pageFunction: '基于URL和标题的备用分析',
      interactiveElements: [
        {
          type: 'input',
          selector: commonSelectors.login.usernameInput,
          description: '用户名输入框',
          suggestedAction: 'fill'
        },
        {
          type: 'input', 
          selector: commonSelectors.login.passwordInput,
          description: '密码输入框',
          suggestedAction: 'fill'
        },
        {
          type: 'button',
          selector: commonSelectors.login.loginButton,
          description: '登录按钮',
          suggestedAction: 'click'
        }
      ],
      recommendedSteps: [
        {
          step: 1,
          action: '等待页面加载完成',
          selector: 'body',
          value: ''
        },
        {
          step: 2,
          action: '查找登录表单元素',
          selector: 'form',
          value: ''
        }
      ],
      confidence: 0.6
    };
  }

  // 识别特定元素
  async recognizeElements(pageInfo, elementTypes) {
    const { title } = pageInfo;
    
    const prompt = this.config.elementRecognitionPrompt
      .replace('{title}', title)
      .replace('{command}', `识别${elementTypes.join(', ')}元素`);

    const messages = [
      {
        role: 'system',
        content: '你是一个专业的网页元素识别助手，擅长提供准确的CSS选择器。'
      },
      {
        role: 'user',
        content: prompt
      }
    ];

    try {
      const recognition = await this.callLLM(messages);
      return this.parseElementRecognition(recognition);
    } catch (error) {
      console.warn('元素识别失败:', error.message);
      return {};
    }
  }

  // 解析元素识别结果
  parseElementRecognition(recognition) {
    try {
      const jsonMatch = recognition.match(/\{[\s\S]*\}/);
      if (jsonMatch) {
        return JSON.parse(jsonMatch[0]);
      }
      return {};
    } catch (error) {
      console.warn('解析元素识别结果失败:', error.message);
      return {};
    }
  }
}

module.exports = LLMService;